home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / bbs / termv4.6 / extras / source / term-source.lha / Phone.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-18  |  26.0 KB  |  1,194 lines

  1. /*
  2. **    Phone.c
  3. **
  4. **    Phonebook support routines
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #ifndef _GLOBAL_H
  11. #include "Global.h"
  12. #endif
  13.  
  14.     /* RemoveDialEntry(struct PhoneNode *Node):
  15.      *
  16.      *    Remove a phone book entry from the dial list.
  17.      */
  18.  
  19. VOID
  20. RemoveDialEntry(struct PhoneNode *Node)
  21. {
  22.     LONG Count = Node -> Entry -> Count,i;
  23.  
  24.     for(i = 0 ; i < NumPhoneEntries ; i++)
  25.     {
  26.         if(Phonebook[i] -> Count > Count)
  27.         {
  28.             SPrintf(Phonebook[i] -> Node -> LocalName,"%3ld - %s",Phonebook[i] -> Count--,Phonebook[i] -> Header -> Name);
  29.  
  30.             if(Phonebook[i] -> NodeGroup)
  31.                 strcpy(Phonebook[i] -> NodeGroup -> LocalName,Phonebook[i] -> Node -> LocalName);
  32.         }
  33.     }
  34.  
  35.     Node -> Entry -> Count = -1;
  36.  
  37.     SPrintf(Node -> LocalName,"      %s",Node -> Entry -> Header -> Name);
  38.  
  39.     if(Node -> Entry -> NodeGroup)
  40.         strcpy(Node -> Entry -> NodeGroup -> LocalName,Node -> LocalName);
  41. }
  42.  
  43.     /* RemoveDialNode(struct PhoneNode *Node):
  44.      *
  45.      *    Remove a node from the dialing list.
  46.      */
  47.  
  48. VOID
  49. RemoveDialNode(struct PhoneNode *Node)
  50. {
  51.     if(Node)
  52.     {
  53.             /* If it's got a name it was built in the phone book panel,
  54.              * else the ARexx interface has linked it into the list.
  55.              */
  56.  
  57.         if(Node -> VanillaNode . ln_Name && Node -> VanillaNode . ln_Name[0])
  58.         {
  59.             LONG Count = Node -> Entry -> Count,i;
  60.  
  61.                 /* Adjust all entries. */
  62.  
  63.             for(i = 0 ; i < NumPhoneEntries ; i++)
  64.             {
  65.                 if(Phonebook[i] -> Count > Count)
  66.                     Phonebook[i] -> Count--;
  67.             }
  68.  
  69.                 /* Can the index count. */
  70.  
  71.             Node -> Entry -> Count = -1;
  72.         }
  73.     }
  74. }
  75.  
  76.     /* SortToList(struct PhoneNode *PhoneNode,struct PhoneEntry *Entry):
  77.      *
  78.      *    Add a node to the dial list.
  79.      */
  80.  
  81. BOOL
  82. SortToList(struct PhoneNode *PhoneNode,struct PhoneEntry *Entry)
  83. {
  84.     BOOL JustCreated = FALSE;
  85.  
  86.         /* No dial list prepared? Let's create one! */
  87.  
  88.     if(!DialList)
  89.     {
  90.         if(DialList = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY))
  91.         {
  92.             NewList(DialList);
  93.  
  94.             JustCreated = TRUE;
  95.         }
  96.     }
  97.  
  98.         /* Do we have a dial list to mangle? */
  99.  
  100.     if(DialList)
  101.     {
  102.         struct PhoneNode *NewNode;
  103.  
  104.             /* Create a new node to be added to the dial list. */
  105.  
  106.         if(NewNode = (struct PhoneNode *)AllocVecPooled(sizeof(struct PhoneNode),MEMF_ANY | MEMF_CLEAR))
  107.         {
  108.             struct PhoneNode *Node = (struct PhoneNode *)DialList -> lh_Head;
  109.  
  110.                 /* Take care of the name and the corresponding phone book entry. */
  111.  
  112.             NewNode -> VanillaNode . ln_Name = NewNode -> LocalName;
  113.  
  114.             if(Entry)
  115.             {
  116.                 NewNode -> Entry = Entry;
  117.  
  118.                 SPrintf(NewNode -> LocalName,"      %s",Entry -> Header -> Name);
  119.             }
  120.             else
  121.             {
  122.                 NewNode -> Entry = PhoneNode -> Entry;
  123.  
  124.                 strcpy(NewNode -> LocalName,PhoneNode -> LocalName);
  125.             }
  126.  
  127.                 /* Install back-link. */
  128.  
  129.             NewNode -> Entry -> Node = NewNode;
  130.  
  131.                 /* Sort the node into the list. */
  132.  
  133.             while(Node -> VanillaNode . ln_Succ)
  134.             {
  135.                 if(Node -> Entry -> Count > NewNode -> Entry -> Count)
  136.                 {
  137.                     if(Node == (struct PhoneNode *)DialList -> lh_Head)
  138.                         AddHead(DialList,&NewNode -> VanillaNode);
  139.                     else
  140.                         Insert(DialList,&NewNode -> VanillaNode,Node -> VanillaNode . ln_Pred);
  141.  
  142.                     return(TRUE);
  143.                 }
  144.  
  145.                 Node = (struct PhoneNode *)Node -> VanillaNode . ln_Succ;
  146.             }
  147.  
  148.             AddTail(DialList,&NewNode -> VanillaNode);
  149.  
  150.             return(TRUE);
  151.         }
  152.     }
  153.  
  154.     if(JustCreated)
  155.     {
  156.         FreeVecPooled(DialList);
  157.         DialList = NULL;
  158.     }
  159.  
  160.     return(FALSE);
  161. }
  162.  
  163.     /* FreeDialList(BOOLEAN ClearAll):
  164.      *
  165.      *    Release the contents of the dial list.
  166.      */
  167.  
  168. VOID
  169. FreeDialList(BOOL ClearAll)
  170. {
  171.     if(DialList)
  172.     {
  173.         struct PhoneNode *SubNode,*NextNode;
  174.  
  175.         for(SubNode = (struct PhoneNode *)DialList -> lh_Head ; NextNode = (struct PhoneNode *)SubNode -> VanillaNode . ln_Succ ; SubNode = NextNode)
  176.         {
  177.             if(ClearAll || !SubNode -> VanillaNode . ln_Name || !SubNode -> VanillaNode . ln_Name[0])
  178.                 FreeVecPooled(SubNode);
  179.         }
  180.  
  181.         FreeVecPooled(DialList);
  182.  
  183.         DialList = NULL;
  184.     }
  185. }
  186.  
  187.     /* CreatePhoneList():
  188.      *
  189.      *    Turn the array of pointers to phonebook entries into
  190.      *    a linked standard Amiga List (gadtools needs this).
  191.      */
  192.  
  193. struct List *
  194. CreatePhoneList()
  195. {
  196.     struct List *PhoneList;
  197.  
  198.     if(Phonebook && NumPhoneEntries)
  199.     {
  200.         struct PhoneNode *PhoneNode;
  201.  
  202.         if(PhoneList = (struct List *)AllocVecPooled(sizeof(struct List) + NumPhoneEntries * sizeof(struct PhoneNode),MEMF_ANY | MEMF_CLEAR))
  203.         {
  204.             LONG i;
  205.  
  206.             NewList(PhoneList);
  207.  
  208.             PhoneNode = (struct PhoneNode *)(PhoneList + 1);
  209.  
  210.             for(i = 0 ; i < NumPhoneEntries ; i++)
  211.             {
  212.                 if(Phonebook[i] -> Count != -1)
  213.                 {
  214.                     SPrintf(PhoneNode[i] . LocalName,"%3ld - %s",Phonebook[i] -> Count + 1,Phonebook[i] -> Header -> Name);
  215.  
  216.                     if(Phonebook[i] -> NodeGroup)
  217.                         strcpy(Phonebook[i] -> NodeGroup -> LocalName,PhoneNode[i] . LocalName);
  218.                 }
  219.                 else
  220.                 {
  221.                     SPrintf(PhoneNode[i] . LocalName,"      %s",Phonebook[i] -> Header -> Name);
  222.  
  223.                     if(Phonebook[i] -> NodeGroup)
  224.                         strcpy(Phonebook[i] -> NodeGroup -> LocalName,PhoneNode[i] . LocalName);
  225.                 }
  226.  
  227.                 PhoneNode[i] . VanillaNode . ln_Name = PhoneNode[i] . LocalName;
  228.  
  229.                 Phonebook[i] -> Node = &PhoneNode[i];
  230.  
  231.                 PhoneNode[i] . Entry = Phonebook[i];
  232.  
  233.                 AddTail(PhoneList,&PhoneNode[i]);
  234.             }
  235.  
  236.             return(PhoneList);
  237.         }
  238.     }
  239.     else
  240.     {
  241.         if(PhoneList = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY))
  242.         {
  243.             NewList(PhoneList);
  244.  
  245.             return(PhoneList);
  246.         }
  247.     }
  248.  
  249.     return(NULL);
  250. }
  251.  
  252.     /* UpdatePhoneList(struct List *PhoneList):
  253.      *
  254.      *    Rebuilds the phone header list, such as after entries got moved.
  255.      */
  256.  
  257. VOID
  258. UpdatePhoneList(struct List *PhoneList)
  259. {
  260.     struct PhoneNode    *PhoneNode;
  261.     LONG             i;
  262.  
  263.     for(i = 0, PhoneNode = (struct PhoneNode *)PhoneList -> lh_Head ; i < NumPhoneEntries && PhoneNode -> VanillaNode . ln_Succ ; i++, PhoneNode = (struct PhoneNode *)PhoneNode -> VanillaNode . ln_Succ)
  264.     {
  265.         if(Phonebook[i] -> Count != -1)
  266.         {
  267.             SPrintf(PhoneNode -> LocalName,"%3ld - %s",Phonebook[i] -> Count + 1,Phonebook[i] -> Header -> Name);
  268.  
  269.             if(Phonebook[i] -> NodeGroup)
  270.                 SPrintf(Phonebook[i] -> NodeGroup -> LocalName,"%3ld - %s",Phonebook[i] -> Count + 1,Phonebook[i] -> Header -> Name);
  271.         }
  272.         else
  273.         {
  274.             SPrintf(PhoneNode -> LocalName,"      %s",Phonebook[i] -> Header -> Name);
  275.  
  276.             if(Phonebook[i] -> NodeGroup)
  277.                 SPrintf(Phonebook[i] -> NodeGroup -> LocalName,"      %s",Phonebook[i] -> Header -> Name);
  278.         }
  279.  
  280.         Phonebook[i] -> Node = PhoneNode;
  281.  
  282.         PhoneNode -> Entry = Phonebook[i];
  283.     }
  284. }
  285.  
  286.     /* DeletePhoneList(struct List *PhoneList):
  287.      *
  288.      *    Delete the entries listed in the Amiga List
  289.      *    created by the routine above.
  290.      */
  291.  
  292. VOID
  293. DeletePhoneList(struct List *PhoneList)
  294. {
  295.     FreeVecPooled(PhoneList);
  296. }
  297.  
  298.     /* PhoneCompare(struct PhoneEntry **A,struct PhoneEntry **B):
  299.      *
  300.      *    Comparison subroutine required by the QuickSort
  301.      *    call below.
  302.      */
  303.  
  304. STATIC LONG __stdargs
  305. PhoneCompare(struct PhoneEntry **A,struct PhoneEntry **B)
  306. {
  307.         /* Has entry A been selected? */
  308.  
  309.     if((*A) -> Count == -1)
  310.     {
  311.             /* If entry B isn't selected either, compare the
  312.              * names lexically, else entry B is supposed
  313.              * to be `smaller' than entry A.
  314.              */
  315.  
  316.         if((*B) -> Count == -1)
  317.             return(Strcoll((*A) -> Header -> Name,(*B) -> Header -> Name));
  318.         else
  319.             return(1);
  320.     }
  321.     else
  322.     {
  323.             /* If entry B isn't selected, entry A is supposed
  324.              * to be `smaller' than entry B, else return
  325.              * the difference between both entries.
  326.              */
  327.  
  328.         if((*B) -> Count == -1)
  329.             return(-1);
  330.         else
  331.             return((*A) -> Count - (*B) -> Count);
  332.     }
  333. }
  334.  
  335. STATIC LONG __stdargs
  336. CompareInverse(struct PhoneEntry **B,struct PhoneEntry **A)
  337. {
  338.     if((*A) -> Count == -1)
  339.     {
  340.         if((*B) -> Count == -1)
  341.             return(Strcoll((*A) -> Header -> Name,(*B) -> Header -> Name));
  342.         else
  343.             return(1);
  344.     }
  345.     else
  346.     {
  347.         if((*B) -> Count == -1)
  348.             return(-1);
  349.         else
  350.             return((*A) -> Count - (*B) -> Count);
  351.     }
  352. }
  353.  
  354. STATIC LONG __stdargs
  355. CompareName(struct PhoneEntry **A,struct PhoneEntry **B)
  356. {
  357.     return(Strcoll((*A) -> Header -> Name,(*B) -> Header -> Name));
  358. }
  359.  
  360. STATIC LONG __stdargs
  361. CompareNumber(struct PhoneEntry **A,struct PhoneEntry **B)
  362. {
  363.     return(Strcoll((*A) -> Header -> Number,(*B) -> Header -> Number));
  364. }
  365.  
  366. STATIC LONG __stdargs
  367. CompareComment(struct PhoneEntry **A,struct PhoneEntry **B)
  368. {
  369.     return(Strcoll((*A) -> Header -> Comment,(*B) -> Header -> Comment));
  370. }
  371.  
  372. STATIC LONG __stdargs
  373. CompareInverseName(struct PhoneEntry **B,struct PhoneEntry **A)
  374. {
  375.     return(Strcoll((*A) -> Header -> Name,(*B) -> Header -> Name));
  376. }
  377.  
  378. STATIC LONG __stdargs
  379. CompareInverseNumber(struct PhoneEntry **B,struct PhoneEntry **A)
  380. {
  381.     return(Strcoll((*A) -> Header -> Number,(*B) -> Header -> Number));
  382. }
  383.  
  384. STATIC LONG __stdargs
  385. CompareInverseComment(struct PhoneEntry **B,struct PhoneEntry **A)
  386. {
  387.     return(Strcoll((*A) -> Header -> Comment,(*B) -> Header -> Comment));
  388. }
  389.  
  390.     /* SortPhoneEntries():
  391.      *
  392.      *    Sorts the current phone list array in ascending order.
  393.      */
  394.  
  395. VOID
  396. SortPhoneEntries(struct List *List,LONG How,BOOL ReverseOrder)
  397. {
  398.     LONG (* __stdargs SortFunc)(struct PhoneEntry **B,struct PhoneEntry **A);
  399.  
  400.     switch(How)
  401.     {
  402.         case SORT_NAME:
  403.  
  404.             if(ReverseOrder)
  405.                 SortFunc = CompareInverseName;
  406.             else
  407.                 SortFunc = CompareName;
  408.  
  409.             break;
  410.  
  411.         case SORT_COMMENT:
  412.  
  413.             if(ReverseOrder)
  414.                 SortFunc = CompareInverseComment;
  415.             else
  416.                 SortFunc = CompareComment;
  417.             break;
  418.  
  419.         case SORT_NUMBER:
  420.  
  421.             if(ReverseOrder)
  422.                 SortFunc = CompareInverseNumber;
  423.             else
  424.                 SortFunc = CompareNumber;
  425.             break;
  426.  
  427.         case SORT_SELECTION:
  428.  
  429.             if(ReverseOrder)
  430.                 SortFunc = CompareInverse;
  431.             else
  432.                 SortFunc = PhoneCompare;
  433.  
  434.             break;
  435.  
  436.         default:
  437.  
  438.             SortFunc = CompareName;
  439.             break;
  440.     }
  441.  
  442.     if(!List)
  443.         QuickSort((APTR)Phonebook,NumPhoneEntries,sizeof(struct PhoneEntry *),SortFunc);
  444.     else
  445.     {
  446.         LONG             Count;
  447.         struct PhoneNode    *Node;
  448.  
  449.         for(Count = 0, Node = (struct PhoneNode *)List -> lh_Head ; Node -> VanillaNode . ln_Succ ; Node = (struct PhoneNode *)Node -> VanillaNode . ln_Succ)
  450.             Count++;
  451.  
  452.         if(Count)
  453.         {
  454.             struct PhoneEntry **Table;
  455.  
  456.             if(Table = (struct PhoneEntry **)AllocVecPooled(sizeof(struct PhoneEntry *) * Count,MEMF_ANY))
  457.             {
  458.                 for(Count = 0, Node = (struct PhoneNode *)List -> lh_Head ; Node -> VanillaNode . ln_Succ ; Node = (struct PhoneNode *)Node -> VanillaNode . ln_Succ)
  459.                     Table[Count++] = Node -> Entry;
  460.  
  461.                 QuickSort((APTR)Table,Count,sizeof(struct PhoneEntry *),SortFunc);
  462.  
  463.                 for(Count = 0, Node = (struct PhoneNode *)List -> lh_Head ; Node -> VanillaNode . ln_Succ ; Node = (struct PhoneNode *)Node -> VanillaNode . ln_Succ)
  464.                 {
  465.                     Node -> Entry            = Table[Count++];
  466.                     Node -> Entry -> NodeGroup    = Node;
  467.  
  468.                     strcpy(Node -> LocalName,Node -> Entry -> Node -> LocalName);
  469.                 }
  470.  
  471.                 FreeVecPooled(Table);
  472.             }
  473.         }
  474.     }
  475. }
  476.  
  477.     /* FreeTimeDateNode(struct TimeDateNode *Node):
  478.      *
  479.      *    Free the memory allocated for a TimeDateNode and
  480.      *    the associated data table.
  481.      */
  482.  
  483. VOID
  484. FreeTimeDateNode(struct TimeDateNode *Node)
  485. {
  486.     FreeVecPooled(Node -> Table);
  487.  
  488.     FreeVecPooled(Node);
  489. }
  490.  
  491.     /* FreeTimeDateList(struct List *List):
  492.      *
  493.      *    Free a list of TimeDateNodes.
  494.      */
  495.  
  496. VOID
  497. FreeTimeDateList(struct List *List)
  498. {
  499.     if(List)
  500.     {
  501.         struct Node *Node;
  502.  
  503.         while(Node = RemHead(List))
  504.             FreeTimeDateNode((struct TimeDateNode *)Node);
  505.     }
  506. }
  507.  
  508.     /* CopyTimeDateList(struct List *From,struct List *To,BOOL SkipFirst):
  509.      *
  510.      *    Copies the TimeDateNode list from one location into
  511.      *    another.
  512.      */
  513.  
  514. VOID
  515. CopyTimeDateList(struct List *From,struct List *To,BOOL SkipFirst)
  516. {
  517.     if(!IsListEmpty(From))
  518.     {
  519.         struct TimeDateNode *FromNode,*ToNode;
  520.  
  521.         FromNode = (struct TimeDateNode *)From -> lh_Head;
  522.  
  523.         if(SkipFirst)
  524.             FromNode = (struct TimeDateNode *)FromNode -> VanillaNode . ln_Succ;
  525.  
  526.         while(FromNode -> VanillaNode . ln_Succ)
  527.         {
  528.             if(ToNode = (struct TimeDateNode *)AllocVecPooled(sizeof(struct TimeDateNode),MEMF_ANY))
  529.             {
  530.                 CopyMem(FromNode,ToNode,sizeof(struct TimeDateNode));
  531.  
  532.                 ToNode -> VanillaNode . ln_Name = ToNode -> Buffer;
  533.  
  534.                 if(ToNode -> Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * FromNode -> Table[0] . Count,MEMF_ANY))
  535.                 {
  536.                     CopyMem(FromNode -> Table,ToNode -> Table,sizeof(struct TimeDate) * FromNode -> Table[0] . Count);
  537.  
  538.                     AddTail(To,&ToNode -> VanillaNode);
  539.                 }
  540.                 else
  541.                     FreeVecPooled(ToNode);
  542.             }
  543.  
  544.             FromNode = (struct TimeDateNode *)FromNode -> VanillaNode . ln_Succ;
  545.         }
  546.     }
  547. }
  548.  
  549.     /* AdaptTimeDateNode(struct TimeDateNode *Node):
  550.      *
  551.      *    Adapt the title and comment of a TimeDateNode.
  552.      */
  553.  
  554. VOID
  555. AdaptTimeDateNode(struct TimeDateNode *Node)
  556. {
  557.     STRPTR Comment = Node -> Header . Comment[0] ? Node -> Header . Comment : LocaleString(MSG_TERMPHONE_NO_COMMENT_TXT);
  558.  
  559.     if(Node -> Header . Month == -1)
  560.     {
  561.         if(Node -> Header . Day == -1)
  562.             strcpy(Node -> Buffer,LocaleString(MSG_TERMPHONE_STANDARD_SETTINGS_TXT));
  563.         else
  564.             SPrintf(Node -> Buffer,LocaleString(MSG_TERMPHONE_DAYS_TXT),Comment);
  565.     }
  566.     else
  567.         SPrintf(Node -> Buffer,"%2ld %s » %s",Node -> Header . Day,LocaleString(MSG_TERMPHONE_JAN_TXT + Node -> Header . Month),Comment);
  568. }
  569.  
  570.     /* TimeCompare(struct TimeDate *A,struct TimeDate *B):
  571.      *
  572.      *    Comparison routine required by SortTimeTable().
  573.      */
  574.  
  575. STATIC LONG __stdargs
  576. TimeCompare(struct TimeDate *A,struct TimeDate *B)
  577. {
  578.     return(((LONG)A -> Time) - ((LONG)B -> Time));
  579. }
  580.  
  581.     /* SortTimeTable(struct TimeDateNode *Node):
  582.      *
  583.      *    Sort the time table associated with a
  584.      *    TimeDateNode in ascending order.
  585.      */
  586.  
  587. VOID
  588. SortTimeTable(struct TimeDateNode *Node)
  589. {
  590.     QuickSort((APTR)Node -> Table,Node -> Table[0] . Count,sizeof(struct TimeDate),TimeCompare);
  591. }
  592.  
  593.     /* BuildTimeList(struct TimeDateNode *Node):
  594.      *
  595.      *    Build a read-to-display time table list from a TimeDateNode.
  596.      */
  597.  
  598. struct List *
  599. BuildTimeList(struct TimeDateNode *Node)
  600. {
  601.     struct List *List;
  602.  
  603.     if(List = (struct List *)AllocVecPooled(sizeof(struct List) + Node -> Table[0] . Count * sizeof(struct TimeNode),MEMF_ANY | MEMF_CLEAR))
  604.     {
  605.         struct TimeNode    *Time = (struct TimeNode *)(List + 1);
  606.         UBYTE         LocalBuffer[40];
  607.         LONG         i;
  608.  
  609.         NewList(List);
  610.  
  611.         for(i = 0 ; i < Node -> Table[0] . Count ; i++)
  612.         {
  613.             Time[i] . VanillaNode . ln_Name    = Time[i] . Name;
  614.             Time[i] . Time            = Node -> Table[i] . Time;
  615.  
  616.             FormatTime(LocalBuffer,Time[i] . Time / 6,(Time[i] . Time % 6) * 10,-1);
  617.  
  618.             LocalBuffer[19] = 0;
  619.  
  620.             strcpy(Time[i] . Name,LocalBuffer);
  621.  
  622.             AddTail(List,&Time[i]);
  623.         }
  624.     }
  625.  
  626.     return(List);
  627. }
  628.  
  629.     /* ResizeTimeDateNode(struct TimeDateNode *Node,LONG Count,UBYTE Time):
  630.      *
  631.      *    Resize the time table associated with a TimeDateNode.
  632.      */
  633.  
  634. BOOL
  635. ResizeTimeDateNode(struct TimeDateNode *Node,LONG Count,UBYTE Time)
  636. {
  637.     if(Count != Node -> Table[0] . Count)
  638.     {
  639.         struct TimeDate *Table;
  640.  
  641.         if(Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  642.         {
  643.             LONG i;
  644.  
  645.             CopyMem(Node -> Table,Table,sizeof(struct TimeDate) * Count);
  646.  
  647.             if(Count > Node -> Table[0] . Count)
  648.             {
  649.                 for(i = Node -> Table[0] . Count ; i < Count ; i++)
  650.                 {
  651.                     CopyMem(&Node -> Table[0],&Table[i],sizeof(struct TimeDate));
  652.  
  653.                     Table[i] . Time = Time;
  654.                 }
  655.             }
  656.  
  657.             for(i = 0 ; i < Count ; i++)
  658.                 Table[i] . Count = Count;
  659.  
  660.             FreeVecPooled(Node -> Table);
  661.  
  662.             Node -> Table = Table;
  663.  
  664.             return(TRUE);
  665.         }
  666.         else
  667.             return(FALSE);
  668.     }
  669.     else
  670.         return(TRUE);
  671. }
  672.  
  673.     /* DeleteTimeDateNode(struct TimeDateNode *Node,LONG Index):
  674.      *
  675.      *    Delete a single timetable entry from a TimeDateNode.
  676.      */
  677.  
  678. BOOL
  679. DeleteTimeDateNode(struct TimeDateNode *Node,LONG Index)
  680. {
  681.     struct TimeDate    *Table;
  682.     LONG         Count = Node -> Table[0] . Count - 1;
  683.  
  684.     if(Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  685.     {
  686.         LONG i,j;
  687.  
  688.         for(i = j = 0 ; i < Node -> Table[0] . Count ; i++)
  689.         {
  690.             if(i != Index)
  691.             {
  692.                 CopyMem(&Node -> Table[i],&Table[j],sizeof(struct TimeDate));
  693.  
  694.                 Table[j++] . Count = Count;
  695.             }
  696.         }
  697.  
  698.         FreeVecPooled(Node -> Table);
  699.  
  700.         Node -> Table = Table;
  701.  
  702.         return(TRUE);
  703.     }
  704.     else
  705.         return(FALSE);
  706. }
  707.  
  708.     /* CreateTimeDateNode(BYTE Month,BYTE Day,STRPTR Comment,LONG Count):
  709.      *
  710.      *    Create a new TimeDateNode including time table entries.
  711.      */
  712.  
  713. struct TimeDateNode *
  714. CreateTimeDateNode(LONG Month,LONG Day,STRPTR Comment,LONG Count)
  715. {
  716.     struct TimeDateNode *Node;
  717.  
  718.     if(Node = (struct TimeDateNode *)AllocVecPooled(sizeof(struct TimeDateNode),MEMF_ANY | MEMF_CLEAR))
  719.     {
  720.         if(Node -> Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  721.         {
  722.             Node -> VanillaNode . ln_Name            = Node -> Buffer;
  723.  
  724.             Node -> Header . Month                = Month;
  725.             Node -> Header . Day                = Day;
  726.  
  727.             Node -> Table[0] . PayPerUnit[DT_FIRST_UNIT]    = 0;
  728.             Node -> Table[0] . SecPerUnit[DT_FIRST_UNIT]    = 0;
  729.             Node -> Table[0] . PayPerUnit[DT_NEXT_UNIT]    = 0;
  730.             Node -> Table[0] . SecPerUnit[DT_NEXT_UNIT]    = 0;
  731.             Node -> Table[0] . Time                = DT_GET_TIME( 0,0);
  732.             Node -> Table[0] . Count            = Count;
  733.  
  734.             if(Count > 1)
  735.             {
  736.                 Node -> Table[1] . PayPerUnit[DT_FIRST_UNIT]    = 0;
  737.                 Node -> Table[1] . SecPerUnit[DT_FIRST_UNIT]    = 0;
  738.                 Node -> Table[1] . PayPerUnit[DT_NEXT_UNIT]    = 0;
  739.                 Node -> Table[1] . SecPerUnit[DT_NEXT_UNIT]    = 0;
  740.                 Node -> Table[1] . Time                = DT_GET_TIME(12,0);
  741.                 Node -> Table[1] . Count            = Count;
  742.             }
  743.  
  744.             strcpy(Node -> Header . Comment,Comment);
  745.  
  746.             AdaptTimeDateNode(Node);
  747.  
  748.             return(Node);
  749.         }
  750.         else
  751.             FreeVecPooled(Node);
  752.     }
  753.  
  754.     return(NULL);
  755. }
  756.  
  757.     /* RemPhoneEntry(struct PhoneNode *Node,LONG Num):
  758.      *
  759.      *    Remove a given entry from the phone book.
  760.      */
  761.  
  762. VOID
  763. RemPhoneEntry(struct PhoneNode *Node,LONG Num)
  764. {
  765.     struct PhoneEntry    *Entry;
  766.     LONG             i;
  767.  
  768.     if(Node)
  769.     {
  770.         for(i = 0 ; i < NumPhoneEntries ; i++)
  771.         {
  772.             if(Phonebook[i] -> Node == Node || Phonebook[i] -> NodeGroup == Node)
  773.             {
  774.                 Num = i;
  775.                 break;
  776.             }
  777.         }
  778.     }
  779.  
  780.     Entry = Phonebook[Num];
  781.  
  782.     for(i = Num ; i < NumPhoneEntries ; i++)
  783.         Phonebook[i] = Phonebook[i + 1];
  784.  
  785.     Phonebook[NumPhoneEntries--] = NULL;
  786.  
  787.     if(Entry -> Config)
  788.         DeleteConfiguration(Entry -> Config);
  789.  
  790.     FreeTimeDateList((struct List *)&Entry -> TimeDateList);
  791.  
  792.         // Is this entry member of a group?
  793.  
  794.     if(Entry -> NodeGroup)
  795.     {
  796.             // Disconnect it
  797.  
  798.         Remove((struct Node *)Entry -> NodeGroup);
  799.  
  800.         FreeVecPooled(Entry -> NodeGroup);
  801.     }
  802.  
  803.     FreeVecPooled(Entry);
  804. }
  805.  
  806.     /* NewPhoneEntry():
  807.      *
  808.      *    Create a new phone book entry with default values and
  809.      *    add it to the array. Expand the phone book if necessary.
  810.      */
  811.  
  812. struct PhoneEntry *
  813. NewPhoneEntry()
  814. {
  815.     struct PhoneEntry    **PrivatePhonebook;
  816.     LONG             PrivatePhoneSize,i;
  817.  
  818.         /* The phone book is filled `to the brim', so let's expand
  819.          * it.
  820.          */
  821.  
  822.     if(NumPhoneEntries + 1 > PhoneSize)
  823.     {
  824.             /* Allocate another phone book. */
  825.  
  826.         if(PrivatePhonebook = CreatePhonebook(PhoneSize + 1,&PrivatePhoneSize,FALSE))
  827.         {
  828.                 /* Copy the data. */
  829.  
  830.             if(Phonebook && PhoneSize)
  831.             {
  832.                 for(i = 0 ; i < PhoneSize ; i++)
  833.                     PrivatePhonebook[i] = Phonebook[i];
  834.  
  835.                     /* Remove the old phonebook. */
  836.  
  837.                 DeletePhonebook(Phonebook,PhoneSize,FALSE);
  838.             }
  839.  
  840.                 /* Assign the new pointers. */
  841.  
  842.             Phonebook = PrivatePhonebook;
  843.             PhoneSize = PrivatePhoneSize;
  844.         }
  845.         else
  846.             return(NULL);
  847.     }
  848.  
  849.         /* Allocate another entry and add it to the phone book. */
  850.  
  851.     if(Phonebook[NumPhoneEntries] = (struct PhoneEntry *)AllocVecPooled(sizeof(struct PhoneEntry) + sizeof(struct PhoneHeader),MEMF_ANY | MEMF_CLEAR))
  852.     {
  853.         if(Phonebook[NumPhoneEntries] -> Config = CreateConfiguration(FALSE))
  854.         {
  855.             struct PhoneEntry *New = Phonebook[NumPhoneEntries];
  856.  
  857.             Phonebook[NumPhoneEntries] -> Header = (struct PhoneHeader *)(Phonebook[NumPhoneEntries] + 1);
  858.  
  859.             strcpy(Phonebook[NumPhoneEntries] -> Header -> Name,LocaleString(MSG_TERMPHONE_UNUSED_ENTRY_TXT));
  860.  
  861.             Phonebook[NumPhoneEntries] -> Count = -1;
  862.  
  863.             Phonebook[NumPhoneEntries] -> Header -> ID = PhonebookID++;
  864.  
  865.             GetSysTime(&Phonebook[NumPhoneEntries] -> Header -> Creation);
  866.  
  867.             NewList((struct List *)&Phonebook[NumPhoneEntries] -> TimeDateList);
  868.  
  869.             NumPhoneEntries++;
  870.  
  871.             return(New);
  872.         }
  873.  
  874.         FreeVecPooled(Phonebook[NumPhoneEntries]);
  875.  
  876.         Phonebook[NumPhoneEntries] = NULL;
  877.     }
  878.  
  879.     return(NULL);
  880. }
  881.  
  882.     /* MergePhonebook(PhonebookHandle *BookHandle):
  883.      *
  884.      *    Merges the current phonebook with new data.
  885.      */
  886.  
  887. struct PhoneEntry **
  888. MergePhonebook(PhonebookHandle *BookHandle)
  889. {
  890.     struct PhoneEntry    **PrivatePhonebook;
  891.     LONG             PrivatePhoneSize = 0;
  892.  
  893.     if(PrivatePhonebook = CreatePhonebook(NumPhoneEntries + BookHandle -> NumPhoneEntries,&PrivatePhoneSize,FALSE))
  894.     {
  895.         LONG i,Count = 0;
  896.  
  897.         for(i = 0 ; i < NumPhoneEntries ; i++)
  898.             PrivatePhonebook[Count++] = Phonebook[i];
  899.  
  900.         for(i = 0 ; i < BookHandle -> NumPhoneEntries ; i++)
  901.         {
  902.             PrivatePhonebook[Count] = BookHandle -> Phonebook[i];
  903.  
  904.             PrivatePhonebook[Count] -> Header -> ID = PhonebookID++;
  905.  
  906.             Count++;
  907.         }
  908.  
  909.         DeletePhonebook(Phonebook,PhoneSize,FALSE);
  910.  
  911.         Phonebook    = PrivatePhonebook;
  912.         PhoneSize    = PrivatePhoneSize;
  913.         NumPhoneEntries    = Count;
  914.     }
  915.  
  916.     return(PrivatePhonebook);
  917. }
  918.  
  919.     /* CreatePhonebook(LONG Size,LONG *AllocSize,BOOL CreateEntries):
  920.      *
  921.      *    Create a new phone entry array (so-called phone book).
  922.      */
  923.  
  924. struct PhoneEntry **
  925. CreatePhonebook(LONG Size,LONG *AllocSize,BOOL CreateEntries)
  926. {
  927.     struct PhoneEntry **PhoneEntry = NULL;
  928.  
  929.     if(Size)
  930.     {
  931.             /* Round the number of phone entries to a
  932.              * multiple of eight.
  933.              */
  934.  
  935.         *AllocSize = (Size + 7) & ~7;
  936.  
  937.             /* Create the list of pointers. */
  938.  
  939.         if(PhoneEntry = (struct PhoneEntry **)AllocVecPooled(*AllocSize * sizeof(struct PhoneEntry *),MEMF_ANY | MEMF_CLEAR))
  940.         {
  941.                 /* And create some entries if necessary. */
  942.  
  943.             if(CreateEntries)
  944.             {
  945.                 BOOL Success = TRUE;
  946.                 LONG i;
  947.  
  948.                 for(i = 0 ; Success && i < Size ; i++)
  949.                 {
  950.                     if(PhoneEntry[i] = (struct PhoneEntry *)AllocVecPooled(sizeof(struct PhoneEntry) + sizeof(struct PhoneHeader),MEMF_ANY | MEMF_CLEAR))
  951.                     {
  952.                         if(PhoneEntry[i] -> Config = CreateConfiguration(FALSE))
  953.                         {
  954.                             PhoneEntry[i] -> Header = (struct PhoneHeader *)(PhoneEntry[i] + 1);
  955.  
  956.                             GetSysTime(&PhoneEntry[i] -> Header -> Creation);
  957.  
  958.                             NewList((struct List *)&PhoneEntry[i] -> TimeDateList);
  959.                         }
  960.                         else
  961.                             Success = FALSE;
  962.                     }
  963.                     else
  964.                         Success = FALSE;
  965.                 }
  966.  
  967.                 if(!Success)
  968.                 {
  969.                     for(i = 0 ; i < *AllocSize ; i++)
  970.                     {
  971.                         if(PhoneEntry[i])
  972.                         {
  973.                             if(PhoneEntry[i] -> Config)
  974.                                 DeleteConfiguration(PhoneEntry[i] -> Config);
  975.  
  976.                             FreeVecPooled(PhoneEntry[i]);
  977.                         }
  978.                     }
  979.  
  980.                     FreeVecPooled(PhoneEntry);
  981.  
  982.                     return(NULL);
  983.                 }
  984.             }
  985.         }
  986.     }
  987.  
  988.     return(PhoneEntry);
  989. }
  990.  
  991.     /* DeletePhonebook(struct PhoneEntry **PhoneBook,LONG Size,BOOL FreeEntries):
  992.      *
  993.      *    Deallocates a given phone book and its entries if necessary.
  994.      */
  995.  
  996. VOID
  997. DeletePhonebook(struct PhoneEntry **Phonebook,LONG Size,BOOL FreeEntries)
  998. {
  999.     if(Phonebook)
  1000.     {
  1001.         if(FreeEntries)
  1002.         {
  1003.             LONG i;
  1004.  
  1005.             for(i = 0 ; i < Size ; i++)
  1006.             {
  1007.                 if(Phonebook[i])
  1008.                 {
  1009.                     FreeTimeDateList((struct List *)&Phonebook[i] -> TimeDateList);
  1010.  
  1011.                     if(Phonebook[i] -> Config)
  1012.                         DeleteConfiguration(Phonebook[i] -> Config);
  1013.  
  1014.                     if(Phonebook[i] -> NodeGroup)
  1015.                     {
  1016.                         Remove((struct Node *)Phonebook[i] -> NodeGroup);
  1017.                         FreeVecPooled(Phonebook[i] -> NodeGroup);
  1018.  
  1019.                         if(!Phonebook[i] -> ThisGroup -> GroupList . mlh_Head -> mln_Succ)
  1020.                         {
  1021.                             Remove((struct Node *)Phonebook[i] -> ThisGroup);
  1022.                             FreeVecPooled(Phonebook[i] -> ThisGroup);
  1023.                         }
  1024.                     }
  1025.  
  1026.                     FreeVecPooled(Phonebook[i]);
  1027.                 }
  1028.             }
  1029.         }
  1030.  
  1031.         FreeVecPooled(Phonebook);
  1032.     }
  1033. }
  1034.  
  1035.     /* DeletePhoneGroupNode(PhoneGroupNode *GroupNode):
  1036.      *
  1037.      *    Delete all PhoneNodes stored in a phone group node list.
  1038.      */
  1039.  
  1040. VOID
  1041. DeletePhoneGroupNode(PhoneGroupNode *GroupNode)
  1042. {
  1043.     struct PhoneNode *Node;
  1044.  
  1045.     while(Node = (struct PhoneNode *)RemHead((struct List *)&GroupNode -> GroupList))
  1046.     {
  1047.         Node -> Entry -> ThisGroup = NULL;
  1048.         Node -> Entry -> NodeGroup = NULL;
  1049.  
  1050.         FreeVecPooled(Node);
  1051.     }
  1052.  
  1053.     FreeVecPooled(GroupNode);
  1054. }
  1055.  
  1056.     /* DeletePhoneGroupList(struct MinList *List):
  1057.      *
  1058.      *    Delete a phone group node and its associated data.
  1059.      */
  1060.  
  1061. VOID
  1062. DeletePhoneGroupList(struct MinList *List)
  1063. {
  1064.     PhoneGroupNode *Node;
  1065.  
  1066.     while(Node = (PhoneGroupNode *)RemHead((struct List *)List))
  1067.         DeletePhoneGroupNode(Node);
  1068. }
  1069.  
  1070.     /* InsertSorted(struct List *List,struct Node *Node):
  1071.      *
  1072.      *    Insert a node into a linked list whilst keeping the
  1073.      *    list sorted in alphabetic order.
  1074.      */
  1075.  
  1076. STATIC VOID
  1077. InsertSorted(struct List *List,struct Node *Node)
  1078. {
  1079.     struct Node    *Other;
  1080.     STRPTR         Name;
  1081.  
  1082.     Name = Node -> ln_Name;
  1083.  
  1084.     for(Other = List -> lh_Head ; Other -> ln_Succ ; Other = Other -> ln_Succ)
  1085.     {
  1086.         if(Strcoll(Name,Other -> ln_Name) <= 0)
  1087.         {
  1088.             if(Other == List -> lh_Head)
  1089.                 AddHead(List,Node);
  1090.             else
  1091.                 Insert(List,Node,Other -> ln_Pred);
  1092.  
  1093.             return;
  1094.         }
  1095.     }
  1096.  
  1097.     AddTail(List,Node);
  1098. }
  1099.  
  1100.     /* CreatePhoneGroup(STRPTR Name,struct MinList *List):
  1101.      *
  1102.      *    Create a phone group with given name, unless the named group
  1103.      *    already exists, in which case the existing group will be returned.
  1104.      */
  1105.  
  1106. PhoneGroupNode *
  1107. CreatePhoneGroup(STRPTR Name,struct MinList *List)
  1108. {
  1109.     PhoneGroupNode *Node;
  1110.  
  1111.     for(Node = (PhoneGroupNode *)List -> mlh_Head ; Node -> Node . ln_Succ ; Node = (PhoneGroupNode *)Node -> Node . ln_Succ)
  1112.     {
  1113.         if(!Stricmp(Node -> Node . ln_Name,Name))
  1114.             return(Node);
  1115.     }
  1116.  
  1117.     if(Node = (PhoneGroupNode *)AllocVecPooled(sizeof(PhoneGroupNode),MEMF_ANY|MEMF_CLEAR))
  1118.     {
  1119.         Node -> Node . ln_Name = Node -> LocalName;
  1120.  
  1121.         strcpy(Node -> LocalName,Name);
  1122.  
  1123.         NewList((struct List *)&Node -> GroupList);
  1124.  
  1125.         InsertSorted((struct List *)List,(struct Node *)Node);
  1126.     }
  1127.  
  1128.     return(Node);
  1129. }
  1130.  
  1131.     /* AddGroupEntry(PhoneGroupNode *NewGroup,struct PhoneNode *Node):
  1132.      *
  1133.      *    Add an entry to a phone group. If the entry is already a member of
  1134.      *    a different group, remove it from the other group and add it to the
  1135.      *    given group. Do nothing if the entry is already a member of the
  1136.      *    given group.
  1137.      */
  1138.  
  1139. struct PhoneNode *
  1140. AddGroupEntry(PhoneGroupNode *NewGroup,struct PhoneNode *Node)
  1141. {
  1142.     if(Node -> Entry -> ThisGroup)
  1143.     {
  1144.         if(Node -> Entry -> ThisGroup == NewGroup)
  1145.             return(Node -> Entry -> NodeGroup);
  1146.         else
  1147.             Remove((struct Node *)Node -> Entry -> NodeGroup);
  1148.     }
  1149.     else
  1150.     {
  1151.         struct PhoneNode *Other;
  1152.  
  1153.         if(Other = (struct PhoneNode *)AllocVecPooled(sizeof(struct PhoneNode),MEMF_ANY|MEMF_CLEAR))
  1154.         {
  1155.             Other -> VanillaNode . ln_Name = Other -> LocalName;
  1156.  
  1157.             Other -> Entry = Node -> Entry;
  1158.  
  1159.             strcpy(Other -> LocalName,Node -> LocalName);
  1160.  
  1161.             Node -> Entry -> NodeGroup = Other;
  1162.         }
  1163.         else
  1164.             return(NULL);
  1165.     }
  1166.  
  1167.     InsertSorted((struct List *)&NewGroup -> GroupList,(struct Node *)Node -> Entry -> NodeGroup);
  1168.  
  1169.     Node -> Entry -> ThisGroup = NewGroup;
  1170.  
  1171.     return(Node -> Entry -> NodeGroup);
  1172. }
  1173.  
  1174.     /* CopyPhoneHeader():
  1175.      *
  1176.      *    Copy a phone header from one place to another. Only copy
  1177.      *    the `sensible' data, not the unique entries.
  1178.      */
  1179.  
  1180. VOID
  1181. CopyPhoneHeader(struct PhoneHeader *From,struct PhoneHeader *To)
  1182. {
  1183.     strcpy(To->Name,From->Name);
  1184.     strcpy(To->Number,From->Number);
  1185.     strcpy(To->Comment,From->Comment);
  1186.  
  1187.     strcpy(To->UserName,From->UserName);
  1188.     strcpy(To->Password,From->Password);
  1189.  
  1190.     To->QuickMenu    = From->QuickMenu;
  1191.     To->NoRates    = From->NoRates;
  1192.     To->AutoDial    = From->AutoDial;
  1193. }
  1194.